#ifndef __TAB_LITE_H__
#define __TAB_LITE_H__

#ifndef TAB_ELEM_NR
#define TAB_ELEM_NR    64
#endif  /* TAB_ELEM_NR */

enum TabTag
{
    TAB_TAG_NIL = 0x00000000,
    TAB_TAG_INT = 0x10101010,
    TAB_TAG_DEC = 0xDECDECDE,
    TAB_TAG_HEX = 0x16161616,
    TAB_TAG_STR = 0x1234ABCD,
    TAB_TAG_TAB = 0xABABABAB,
};
typedef enum TabTag TabTag;

enum TabError
{
    TAB_ERROR_OK = 0,
    TAB_ERROR_ARG,
    TAB_ERROR_NOMEM,
    TAB_ERROR_NOFOUND,
    TAB_ERROR_FAULT,
    TAB_ERROR_NR
};
typedef enum TabError TabError;

struct TabLite;
struct TabElem
{
    union 
    {
        double decimal;
        long integer;
        unsigned long hexadecimal;
        char *string;                   /* when del elem, need free this string */
        struct TabLite* subTable;
    } value;
#define valDec value.decimal
#define valInt value.integer
#define valHex value.hexadecimal
#define valStr value.string
#define valTab value.subTable
    unsigned long hashKey;  /* hash key for name of elem */
    TabTag tag;         /* tag of this element */
};
typedef struct TabElem TabElem;

struct TabLite
{
    struct TabElem elems[TAB_ELEM_NR];  /* elems in table */
    struct TabLite* next;               /* next table */
};
typedef struct TabLite TabLite;

TabLite* TabLiteNew();
int TabLiteDel(TabLite* tab);

TabElem *TabLiteGetByKey(TabLite* tab, char* name);
TabElem *TabLiteGetByIndex(TabLite* tab, unsigned long index);
TabLite* TabLiteSetByKey(TabLite* tab, char* name, TabElem* elem);
TabElem* TabElemSetStr(TabElem* elem, char *str);
char* TabElemGetStr(TabElem* elem);
TabLite* TabLiteRemoveByKey(TabLite* tab, char* name);

#define TabLiteGet(tab, name) TabLiteGetByKey(tab, name)
#define TabLiteSet(tab, name, elem) TabLiteSetByKey(tab, name, elem)
#define TabElemSet(elem, value) TabElemSetStr(elem, value)
#define TabElemGet(elem) TabElemGetStr(elem)
#define TabLiteRemove(tab, name) TabLiteRemoveByKey(tab, name)
#define TabElemGetTag(elem) (elem)->tag

#define TAB_ELEM_FIRST(tab) (&(tab)->elems[0])
#define TAB_ELEM_LAST(tab) (&(tab)->elems[TAB_ELEM_NR - 1])

#define ForEachTabElem(tab, elem) \
    for ((elem) = TAB_ELEM_FIRST(tab); (elem) <= TAB_ELEM_LAST(tab); (elem)++)

void TabLiteDump(TabLite* tab);
void TabElemDump(TabElem* elem);

int TabLiteAttach(TabLite* parent, TabLite* child);
int TabLiteDetach(TabLite* parent, TabLite* child);

TabElem* TabElemSetInt(TabElem* elem, long value);
TabElem* TabElemSetDec(TabElem* elem, double value);
TabElem* TabElemSetHex(TabElem* elem, unsigned long value);
TabElem* TabElemSetTab(TabElem* elem, TabLite* tab);

long TabElemGetInt(TabElem* elem);
double TabElemGetDec(TabElem* elem);
unsigned long TabElemGetHex(TabElem* elem);
TabLite* TabElemGetTab(TabElem* elem);

TabElem *TabLiteGetByNext(TabLite* tab, TabElem *next);

void TabErrorSet(TabError err);
char *TabErrorGet();

#endif  /* __TAB_LITE_H__ */